package com.kexio.dynamic.config.service.impl;

import com.kexio.common.util.JsonUtils;
import com.kexio.dynamic.config.service.ConfigChangeListener;
import com.kexio.dynamic.config.service.ConfigService;
import com.kexio.dynamic.config.service.DynamicConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 动态配置服务默认实现
 * 
 * 提供配置的动态更新、监听和热加载功能
 * 
 * @author Kexio
 * @since 1.0.0
 */
@Service
public class DefaultDynamicConfigService implements DynamicConfigService {

    private static final Logger log = LoggerFactory.getLogger(DefaultDynamicConfigService.class);
    private final ConfigService configService;
    
    public DefaultDynamicConfigService(ConfigService configService) {
        this.configService = configService;
    }
    
    /**
     * 配置监听器映射 (configKey -> listeners)
     */
    private final Map<String, List<ConfigChangeListener>> configListeners = new ConcurrentHashMap<>();
    
    /**
     * 分组监听器映射 (groupPattern -> listeners)  
     */
    private final Map<String, List<ConfigChangeListener>> groupListeners = new ConcurrentHashMap<>();
    
    /**
     * 配置最后更新时间缓存
     */
    private final Map<String, Long> lastUpdateTimes = new ConcurrentHashMap<>();

    @Override
    public String getStringValue(String key, String defaultValue) {
        updateLastAccessTime(key);
        return configService.getValue(key, defaultValue);
    }

    @Override
    public Integer getIntValue(String key, Integer defaultValue) {
        updateLastAccessTime(key);
        return configService.getIntValue(key, defaultValue);
    }

    @Override
    public Boolean getBooleanValue(String key, Boolean defaultValue) {
        updateLastAccessTime(key);
        return configService.getBooleanValue(key, defaultValue);
    }

    @Override
    public Long getLongValue(String key, Long defaultValue) {
        updateLastAccessTime(key);
        return configService.getLongValue(key, defaultValue);
    }

    @Override
    public Double getDoubleValue(String key, Double defaultValue) {
        updateLastAccessTime(key);
        return configService.getDoubleValue(key, defaultValue);
    }

    @Override
    public <T> T getJsonValue(String key, Class<T> clazz) {
        updateLastAccessTime(key);
        return configService.getJsonValue(key, clazz);
    }

    @Override
    public List<String> getListValue(String key, String separator) {
        String value = getStringValue(key, null);
        if (!StringUtils.hasText(value)) {
            return Collections.emptyList();
        }
        
        return Arrays.asList(value.split(separator != null ? separator : ","));
    }

    @Override
    @Async
    public CompletableFuture<Boolean> updateConfig(String key, String value) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                String oldValue = configService.getValue(key);
                boolean updated = configService.updateValue(key, value);
                
                if (updated) {
                    updateLastAccessTime(key);
                    notifyConfigChange(key, oldValue, value);
                    log.info("配置更新成功: key={}, oldValue={}, newValue={}", key, oldValue, value);
                }
                
                return updated;
            } catch (Exception e) {
                log.error("配置更新失败: key={}, value={}", key, value, e);
                return false;
            }
        });
    }

    @Override
    @Async
    public CompletableFuture<Integer> updateConfigs(Map<String, String> configs) {
        return CompletableFuture.supplyAsync(() -> {
            if (configs == null || configs.isEmpty()) {
                return 0;
            }
            
            int successCount = 0;
            for (Map.Entry<String, String> entry : configs.entrySet()) {
                try {
                    CompletableFuture<Boolean> result = updateConfig(entry.getKey(), entry.getValue());
                    if (result.get()) {
                        successCount++;
                    }
                } catch (Exception e) {
                    log.error("批量更新配置失败: key={}, value={}", entry.getKey(), entry.getValue(), e);
                }
            }
            
            log.info("批量配置更新完成: 总数={}, 成功数={}", configs.size(), successCount);
            return successCount;
        });
    }

    @Override
    public void addConfigListener(String key, ConfigChangeListener listener) {
        if (!StringUtils.hasText(key) || listener == null) {
            return;
        }
        
        configListeners.computeIfAbsent(key, k -> new CopyOnWriteArrayList<>()).add(listener);
        log.debug("添加配置监听器: key={}, listener={}", key, listener.getListenerName());
    }

    @Override
    public void addGroupListener(String groupPattern, ConfigChangeListener listener) {
        if (!StringUtils.hasText(groupPattern) || listener == null) {
            return;
        }
        
        groupListeners.computeIfAbsent(groupPattern, k -> new CopyOnWriteArrayList<>()).add(listener);
        log.debug("添加分组监听器: groupPattern={}, listener={}", groupPattern, listener.getListenerName());
    }

    @Override
    public void removeConfigListener(String key, ConfigChangeListener listener) {
        if (!StringUtils.hasText(key) || listener == null) {
            return;
        }
        
        List<ConfigChangeListener> listeners = configListeners.get(key);
        if (listeners != null) {
            listeners.remove(listener);
            if (listeners.isEmpty()) {
                configListeners.remove(key);
            }
        }
        
        log.debug("移除配置监听器: key={}, listener={}", key, listener.getListenerName());
    }

    @Override
    public void refreshConfig(String key) {
        if (!StringUtils.hasText(key)) {
            return;
        }
        
        // 清除缓存并重新加载
        configService.refreshCache();
        updateLastAccessTime(key);
        
        log.info("刷新配置: key={}", key);
    }

    @Override
    public void refreshGroup(String group) {
        if (!StringUtils.hasText(group)) {
            return;
        }
        
        // 刷新整个分组的配置
        configService.refreshCache();
        log.info("刷新配置分组: group={}", group);
    }

    @Override
    public void refreshAllConfigs() {
        configService.refreshCache();
        lastUpdateTimes.clear();
        log.info("刷新所有配置完成");
    }

    @Override
    public void warmupCache(List<String> keys) {
        if (keys == null || keys.isEmpty()) {
            return;
        }
        
        for (String key : keys) {
            try {
                configService.getValue(key);
                updateLastAccessTime(key);
            } catch (Exception e) {
                log.warn("预热配置缓存失败: key={}", key, e);
            }
        }
        
        log.info("配置缓存预热完成: 配置数量={}", keys.size());
    }

    @Override
    public Long getLastUpdateTime(String key) {
        return lastUpdateTimes.get(key);
    }

    @Override
    public boolean exists(String key) {
        return configService.getConfig(key) != null;
    }

    @Override
    public String getRawValue(String key) {
        return configService.getValue(key);
    }

    @Override
    public String getEncryptedValue(String key) {
        // TODO: 实现配置值加密功能
        return getRawValue(key);
    }

    @Override
    public boolean setEncrypted(String key, boolean encrypted) {
        // TODO: 实现配置加密状态设置
        return false;
    }

    /**
     * 通知配置变更
     */
    private void notifyConfigChange(String key, String oldValue, String newValue) {
        // 通知特定配置的监听器
        List<ConfigChangeListener> keyListeners = configListeners.get(key);
        if (keyListeners != null) {
            for (ConfigChangeListener listener : keyListeners) {
                try {
                    if (listener.isAsync()) {
                        executeAsyncNotification(listener, key, oldValue, newValue);
                    } else {
                        listener.onConfigChange(key, oldValue, newValue);
                    }
                } catch (Exception e) {
                    log.error("配置变更通知失败: key={}, listener={}", key, listener.getListenerName(), e);
                }
            }
        }
        
        // 通知分组监听器
        for (Map.Entry<String, List<ConfigChangeListener>> entry : groupListeners.entrySet()) {
            String pattern = entry.getKey();
            if (matchPattern(key, pattern)) {
                for (ConfigChangeListener listener : entry.getValue()) {
                    try {
                        if (listener.isAsync()) {
                            executeAsyncNotification(listener, key, oldValue, newValue);
                        } else {
                            listener.onConfigChange(key, oldValue, newValue);
                        }
                    } catch (Exception e) {
                        log.error("分组配置变更通知失败: key={}, pattern={}, listener={}", 
                                key, pattern, listener.getListenerName(), e);
                    }
                }
            }
        }
    }

    /**
     * 异步执行配置变更通知
     */
    @Async
    private void executeAsyncNotification(ConfigChangeListener listener, String key, String oldValue, String newValue) {
        listener.onConfigChange(key, oldValue, newValue);
    }

    /**
     * 模式匹配（支持通配符）
     */
    private boolean matchPattern(String text, String pattern) {
        if (pattern.equals("*")) {
            return true;
        }
        if (pattern.contains("*")) {
            String regex = pattern.replace("*", ".*");
            return text.matches(regex);
        }
        return text.equals(pattern);
    }

    /**
     * 更新配置的最后访问时间
     */
    private void updateLastAccessTime(String key) {
        lastUpdateTimes.put(key, System.currentTimeMillis());
    }
}
